package com.ahmedmisbah.andgenplus.utils.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.ahmedmisbah.andgenplus.constants.GlobalConstants;
import com.ahmedmisbah.andgenplus.utils.file.exceptions.FileUtilException;

/**
 * 
 * @author Ahmed Misbah
 */
public class FileUtil {

	public static void writeFile(String data, String path, String encoding)
			throws FileUtilException {
		FileOutputStream fos;
		File file = new File(path);
		file.getParentFile().mkdirs();
		try {
			fos = new FileOutputStream(path);
			OutputStreamWriter osw = new OutputStreamWriter(fos, encoding);
			osw.write(data);
			osw.flush();
			osw.close();
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			throw new FileUtilException(e);
		} catch (IOException e) {
			throw new FileUtilException(e);
		}
	}

	public static void writeFileAsUTF8(String data, String path)
			throws FileUtilException {
		FileOutputStream fos;
		File file = new File(path);
		file.getParentFile().mkdirs();
		try {
			fos = new FileOutputStream(path);
			OutputStreamWriter osw = new OutputStreamWriter(fos,
					GlobalConstants.DEFAULT_ENCODING);
			osw.write(data);
			osw.flush();
			osw.close();
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			throw new FileUtilException(e);
		} catch (IOException e) {
			throw new FileUtilException(e);
		}
	}

	public static String readFile(String path, String encoding)
			throws FileUtilException {
		StringBuilder ret = new StringBuilder();

		FileInputStream fis;
		try {
			fis = new FileInputStream(path);
			InputStreamReader isr = new InputStreamReader(fis, encoding);
			BufferedReader stdin = new BufferedReader(isr);

			String line = "";

			do {

				line = stdin.readLine();
				if (line != null) {
					ret.append(line).append("\n");
				}

			} while (line != null);

			ret.deleteCharAt(ret.length() - 1);

			stdin.close();
			isr.close();
			fis.close();
		} catch (FileNotFoundException e) {
			throw new FileUtilException(e);
		} catch (IOException e) {
			throw new FileUtilException(e);
		}

		return ret.toString();
	}

	public static boolean exists(String filePath) {
		boolean ret = false;

		File file = new File(filePath);

		if (file.exists()) {
			ret = true;
		}

		return ret;
	}

	public static boolean exists(URL url) {
		boolean ret = false;

		Object fileContent;
		try {
			fileContent = url.getContent();
			ret = true;
		} catch (IOException ex) {
			ex.printStackTrace();
		}

		return ret;
	}

	public static List<String> getAllFiles(String filePath) {
		List<String> ret = new ArrayList<String>();

		File file = new File(filePath);

		if (file.isDirectory()) {
			for (File childFiles : file.listFiles()) {
				ret.addAll(getAllFiles(childFiles.getAbsolutePath()));
			}
		} else {
			ret.add(filePath);
		}

		return ret;
	}

	public static List<String> getAllFilesAndParent(String filePath, int limit) {
		List<String> ret = new ArrayList<String>();

		File file = new File(filePath);

		if (file.isDirectory()) {
			for (File childFiles : file.listFiles()) {
				ret.addAll(getAllFilesAndParent(childFiles.getAbsolutePath(),
						limit));
			}
		} else {
			String shortFilename = getFilenameAndParent(filePath, limit);
			ret.add(shortFilename);
		}

		return ret;
	}

	public static List<String> getAllFileNames(String filePath) {
		List<String> ret = new ArrayList<String>();

		File file = new File(filePath);

		if (file.exists()) {

			if (file.isDirectory()) {
				for (File childFiles : file.listFiles()) {
					ret.addAll(getAllFileNames(childFiles.getAbsolutePath()));
				}
			} else {
				String filename = getFilename(filePath);
				ret.add(filename);
			}
		}

		return ret;
	}

	/**
	 * Return file path in the following format "Eman Parser/html/1/1.html"
	 * 
	 * @param filePath
	 * @return
	 */
	public static String getFilenameAndParent(String filePath, int limit) {
		StringBuilder ret = new StringBuilder("");

		String[] splitFilePath = filePath.split("\\\\");

		int startIndex = splitFilePath.length - limit;
		int endIndex = splitFilePath.length;

		for (int i = startIndex; i < endIndex; i++) {
			ret.append(splitFilePath[i]);

			if (i + 1 != endIndex) {
				ret.append(File.separator);
			}

		}

		return ret.toString();

	}

	public static String getFilename(String filePath) {
		String ret = null;

		String[] splitFilePath = filePath.split("\\\\");

		ret = splitFilePath[splitFilePath.length - 1].split("\\.")[0];

		return ret;

	}

	/**
	 * Moves file from one location to another
	 * 
	 * @param file
	 */
	public static void copyFile(String sourcePath,
			String destinationPath) throws FileUtilException {


		try {
			FileInputStream fis = new FileInputStream(sourcePath);
			BufferedInputStream bis = new BufferedInputStream(fis);

			FileOutputStream fos = new FileOutputStream(destinationPath);
			BufferedOutputStream bos = new BufferedOutputStream(fos);

			byte[] buffer = new byte[GlobalConstants.BUFFER_SIZE];
			int bytesRead = 0;

			while ((bytesRead = bis.read(buffer)) != -1) {
				bos.write(buffer, 0, bytesRead);
			}

			bos.flush();

			fos.close();
			fis.close();

			bos.close();
			bis.close();
		} catch (IOException e) {
			throw new FileUtilException(e);
		}

	}

}
